package com.ecar.api.quartz.jobs;

import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.print.attribute.standard.Sides;

import net.sf.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import com.ecar.api.service.common.ActivityService;
import com.ecar.api.service.common.NotifyService;
import com.ecar.api.service.driver.CarService;
import com.ecar.api.service.driver.DriverService;
import com.ecar.api.service.order.OrderService;
import com.ecar.api.support.dto.Constants;
import com.ecar.api.support.dto.order.DriverWilddogDto;
import com.ecar.api.support.util.DateUtil;
import com.ecar.api.support.util.GaoDeMapUtil;
import com.ecar.api.support.util.OrderUtil;
import com.ecar.api.support.util.Props;
import com.ecar.api.support.util.Redis;
import com.ecar.api.support.util.WilddogUtil;
import com.ecar.common.dto.DataBean;
import com.ecar.common.util.BeanUtils;
import com.ecar.common.util.DataValidateUtil;
import com.ecar.common.util.StringUtil;
import com.ecar.core.common.entity.Coupon;
import com.ecar.core.common.entity.CouponActivities;
import com.ecar.core.driver.dao.ModelSetMapper;
import com.ecar.core.driver.entity.Car;
import com.ecar.core.driver.entity.Driver;
import com.ecar.core.driver.entity.ModelSet;
import com.ecar.core.order.entity.Order;
import com.wilddog.client.DataSnapshot;
import com.wilddog.client.SyncError;
import com.wilddog.client.SyncReference;
import com.wilddog.client.ValueEventListener;

/**
 * 定时发生未派出的订单
 * Created by fire on 2017/6/1.
 * @noinspection unused
 */
public class SendOrderJob {

	private static final Logger log = LoggerFactory.getLogger(SendOrderJob.class);

	@Autowired
	OrderService orderService;

	@Autowired
	DriverService driverService;

	@Autowired
	ModelSetMapper modelSetMapper;

	@Autowired
	CarService carService;

	@Autowired
	NotifyService notifyService;
	
	@Autowired
	ActivityService activityService;

	/**
	 * 该方法只对20分钟后的未派送的订单进行超时处理
	 * @throws Exception
	 */
	public void overTimeOrder() throws Exception{
		System.out.println("=========未派送订单超时处理定时任务=========="+DateUtil.getCurDateTime());
		final List<Order> list = orderService.overTimeOrder();
		log.info("共有{}个超时订单",list.size());
		if(list.size()<=0){
			return;
		}
		WilddogUtil.getPassengerRef("WilddogLocation/order").addListenerForSingleValueEvent(new ValueEventListener() {
			@Override
			public void onDataChange(DataSnapshot dataSnapshot) {
				for(Order order :list){
					if(dataSnapshot.hasChild(order.getOrderNum())){
						String key=Redis.K.OVERTIME_ORDER.to(order.getOrderNum());
						if(Redis.c.exists(key)){
							continue;
						}
						Map<String, Object> map=new HashMap<String, Object>();
						order.setOrderStatus(0);
						map=orderService.sendToPassengerTemp(order);
						WilddogUtil.getPassengerRef("WilddogLocation/order").child(order.getOrderNum()).updateChildren(map);
						int EXPIRE = 600;
						Redis.c.setex(Redis.K.OVERTIME_ORDER.to(order.getOrderNum()), EXPIRE, "0");

					}
				}

			}
			@Override
			public void onCancelled(SyncError arg0) {
			}
		});
	}
	/**
	 * 该方法只对未派送的订单进行派送
	 * @throws Exception
	 */
	public void sendOrder() throws Exception{
		System.out.println("=========未派送订单派送定时任务=========="+DateUtil.getCurDateTime());
		List<Order> list=orderService.selectUnsendOrder();
		log.info("共有{}个未派送的订单",list.size());
		for(Order order:list){
			String key = Redis.K.ORDER_SEND.to(order.getOrderNum());
			int count=0;
			if(Redis.c.exists(key)){
				count=Integer.valueOf(Redis.c.get(key));
			}else{
				//添加redis的缓存
				int EXPIRE = 1800;
				Redis.c.setex(Redis.K.ORDER_SEND.to(order.getOrderNum()), EXPIRE, "1");
			}
			if(count>5){
				log.info("订单{}将被强制派送",order.getOrderNum());
				orderService.sendNowOrder(order.getOrderNum());
			}else{
				String flag = Redis.K.ORDER_SENDED.to(order.getOrderNum());
				if(Redis.c.exists(flag)){
					log.info("该订单已发送给司机");
				}else{
					int EXPIRE = 45;
					Redis.c.setex(Redis.K.ORDER_SENDED.to(order.getOrderNum()), EXPIRE, "1");
					int p = orderService.sendOrder(order);
					if(p==400){
						log.info("订单{}已有司机接单",order.getOrderNum());
						continue;
					}
				}
			}
		}
	}
	/**
	 * 
	 * 将未派送的预约单，进行强制派送
	 * @throws Exception
	 */
	public void sendAppointmentOrder() throws Exception{
		System.out.println("=========预约单提前半小时强制派单=========="+DateUtil.getCurDateTime());
		final List<Order> list=orderService.selectAppointmentOrder();
		log.info("共有{}个未派送的预约订单",list.size());
		if(list.size()==0){
			return;
		}
		//1.16为了预约单派送时，同一司机多订单进入派送流程的bug
		for(final Order order:list){
		WilddogUtil.getPassengerRef("WilddogLocation/order").addListenerForSingleValueEvent(new ValueEventListener() {
			@Override
			public void onDataChange(DataSnapshot dataSnapshot) {
					log.info("订单{}",order.getOrderNum());
					if(order.getOrderStatus()==3){
						if(!dataSnapshot.child(order.getDriverId()).hasChild("now")){
							log.info("写给乘客和司机");
							Driver driver=driverService.selectByPrimaryKey(order.getDriverId());
							HashMap<String, Object> driverMap=orderService.sendToDriver(order, driver, 3,"");

							if(driverMap==null){
								log.info("订单派送失败");
								return;
							}
							Map<String, Object> map=(Map<String, Object>) driverMap.get(order.getOrderNum());
							map.put("carpool", order.getOrderNum());
							HashMap<String, Object> resultMap=new HashMap<String, Object>();
							resultMap.put(order.getOrderNum(), map);
							WilddogUtil.sendNowOrderToDriver(order.getDriverId(), resultMap);
							//WilddogUtil.sendMessage(WilddogUtil.getDriverRef("WilddogLocation/order"), order.getDriverId()+"/now", driverResult);
							modelSetMapper.stopGetOrder(driver.getId());
							//修改订单的状态为已派单
							orderService.updateByDriverId(7, order.getOrderNum());
							String content = Props.getValue("sms.msg.appointment.driver");
							content = MessageFormat.format(content, DateUtil.parseDateToString(order.getPlanTime(),"yyyy-MM-dd HH:mm:ss"),order.getStartAddress(),order.getDesAddress(),driver.getPhone());
							notifyService.sendSingleSMS(driverService.selectByPrimaryKey(order.getDriverId()).getPhone(), content);
							notifyService.sendSingleSMS(order.getPassengerPhone(), content);
						}else{
							log.info("司机尚有订单未完成");
							//需要给司机发短信提醒
							String key = Redis.K.SMS_DRIVER.to(order.getOrderNum());
							//当redis里有数据是继续
							if(!Redis.c.exists(key)){
								String content = Props.getValue("sms.msg.appointment.driver3");
								content = MessageFormat.format(content, DateUtil.parseDateToString(order.getPlanTime(),"yyyy-MM-dd HH:mm:ss"),order.getStartAddress(),order.getDesAddress(),order.getPassengerPhone());
								notifyService.sendSingleSMS(driverService.selectByPrimaryKey(order.getDriverId()).getPhone(), content);
								notifyService.sendSingleSMS(order.getPassengerPhone(), content);
								int EXPIRE = 1800;
								Redis.c.setex(Redis.K.SMS_DRIVER.to(order.getOrderNum()), EXPIRE, "1");

							}
						}
					}
				}
			@Override
			public void onCancelled(SyncError arg0) {
			}
		});
		}
	}

	/**
	 * 
	 * 将未派送的预约单，进行改派处理
	 * @throws Exception
	 */
	public void appointmentToNowOrder() throws Exception{
		System.out.println("=========预约单改派=========="+DateUtil.getCurDateTime());
		List<Order> orders=orderService.selectAppointmentToNowOrder();
		for(final Order order:orders){
			ModelSet modelSet=modelSetMapper.selectByDriverId(order.getDriverId());
			if(modelSet.getStatus()==1){
				log.info("预约单写给司机");
				Driver driver=driverService.selectByPrimaryKey(order.getDriverId());
				HashMap<String, Object> driverMap=orderService.sendToDriver(order, driver, 3,"");
				if(driverMap==null){
					log.info("订单派送失败");
					continue;
				}
				WilddogUtil.sendNowOrderToDriver(order.getDriverId(), driverMap);
				modelSetMapper.stopGetOrder(driver.getId());
				//修改订单的状态为已派单
				orderService.updateByDriverId(7, order.getOrderNum());
				String content = Props.getValue("sms.msg.appointment.driver");
				content = MessageFormat.format(content, DateUtil.parseDateToString(order.getPlanTime(),"yyyy-MM-dd HH:mm:ss"),order.getStartAddress(),order.getDesAddress(),order.getPassengerPhone());
				notifyService.sendSingleSMS(driverService.selectByPrimaryKey(order.getDriverId()).getPhone(), content);
				notifyService.sendSingleSMS(order.getPassengerPhone(), content);
			}else{
				String content = Props.getValue("sms.msg.orderChange.driver");
				content = MessageFormat.format(content, DateUtil.parseDateToString(order.getPlanTime(),"yyyy-MM-dd HH:mm:ss"),order.getStartAddress(),order.getDesAddress());
				notifyService.sendSingleSMS(driverService.selectByPrimaryKey(order.getDriverId()).getPhone(), content);
				content = Props.getValue("sms.msg.orderChange.passenger");
				notifyService.sendSingleSMS(order.getPassengerPhone(), content);
				order.setOrderStatus(2);
				order.setOrderType(3);
				order.setDriverId(null);
				order.setCreateTime(new Date());
				orderService.updateByPrimaryKeySelective(order);
			}
		}
	}

	/**
	 * parent_order栏如果等于自己的ID，即已拼车的订单
	 * 拼车
	 */
	public void carpool()throws Exception{
		System.out.println("=========拼车单派单=========="+DateUtil.getCurDateTime());
		final List<Order> list=orderService.selectCarpoolParentOrder();
		log.info("共有{}个拼车单",list.size());
		if(list.size()==0){
			return;
		}
		SyncReference driverRef = WilddogUtil.getDriverRef("WilddogLocation/map");
		driverRef.addListenerForSingleValueEvent(new ValueEventListener() {
			//获取到所有已成的拼车单
			@Override
			public void onDataChange(DataSnapshot dataSnapshot) {
				for(final Order order:list){
					log.info("当前正在寻找子订单的父订单为"+order.getOrderNum());
					//按人不按单
					/*List<Order> aaaa=orderService.selectOrderByParentOrder(order.getOrderNum());
					if(aaaa.size()>=3){
						log.info("该订单已经有拼了3单");
						continue;
					}*/
					String leftSeatKey = Redis.K.ORDER_CARPOOL.to(order.getOrderNum());
					if(!Redis.c.exists(leftSeatKey)){
						log.info("redis没有该订单{}座位数",order.getOrderNum());
						continue;
					}
					String leftSeatString=Redis.c.get(leftSeatKey);
					Integer leftSeat=Integer.valueOf(leftSeatString);
					if(leftSeat<=0){
						//如果redis里存在该订单号，就说明该订单乘客已经满了
						log.info("该订单没有空余座位");
						continue;
					}
					String parentStart = order.getStartLocation();
					parentStart=parentStart.replace(":", ",");
					String parentEnd=order.getDesLocation();
					parentEnd=parentEnd.replace(":", ",");
					double distanceb=GaoDeMapUtil.getDistance(parentStart, parentEnd);
					if(distanceb==-1){
						log.info("行程查询失败");
						continue;
					}
					log.info("行程总距离为"+distanceb);
					//获取司机的实时定位
					double x=(double) dataSnapshot.child(order.getDriverId()).child("location").child("0").getValue();
					double y=(double) dataSnapshot.child(order.getDriverId()).child("location").child("1").getValue();
					//司机的坐标点
					String driverLocation =x + "," + y; 
					/*double distancea=GaoDeMapUtil.getDistance(parentStart, driverLocation);
					if(distancea==-1){
						log.info("行程查询失败");
						continue;
					}
					log.info("司机{}距离起点的距离为"+distancea,order.getDriverId());*/
					double distancea=GaoDeMapUtil.getDistance(parentEnd, driverLocation);
					if(distancea==-1){
						log.info("司机距离终点距离查询失败");
						continue;
					}
					log.info("司机{}距离终点的距离为"+distancea,order.getDriverId());
					//路程开始25%就不再匹配
					/*if(distanceb*0.25<=distancea && order.getOrderStatus()==4){
						log.info("行程已开始了25%，不再匹配");
						continue;
					}*/
					//获取未派发的拼车单A
					List<Order> temp=orderService.selectCarpoolOrderBySeat(leftSeat);
					if(temp.size()==0){
						log.info("未找到可拼的订单,进入下一次匹配");
						continue;
					}
					for(int i=0;i<temp.size();i++){
						final Order sonOrder=temp.get(i);
						//获取当前订单的座位数
						Integer seat2=sonOrder.getUseSeats();
						String sonEnd=sonOrder.getDesLocation();
						sonEnd=sonEnd.replace(":", ",");
						double distance=GaoDeMapUtil.getDistance(sonEnd, parentEnd);
						if(distance==-1){
							log.info("父子订单终点距离查询失败");
							continue;
						}

						String sonStart=sonOrder.getStartLocation();
						sonStart=sonStart.replace(":", ",");
						//比对司机离终点距离，和子单的行程距离
						double distanceSon=GaoDeMapUtil.getDistance(sonStart, sonEnd);
						if(distance==-1){
							log.info("子订单行程查询失败，进入下一轮匹配");
							continue;
						}
						//司机离终点行程加1km宽限
						if(distanceSon>distancea+1000.0){
							log.info("子订单{}行程距离为{}，司机行程距离为{},进入下一轮匹配",sonOrder.getOrderNum(),distanceSon,distancea);
							continue;
						}
						log.info("子订单{}行程距离为"+distanceSon,sonOrder.getOrderNum());
						//通过高德获取距离
						double distanced=GaoDeMapUtil.getDistance(sonStart, driverLocation);
						if(distanced==-1){
							log.info("乘客距离司机行程查询失败");
							continue;
						}
						//前一个distance是终点距离，后一个是起点距离
						if(distance<=5000.0 && distanced<=5000.0){
							log.info("两订单{}终点距离{}米",sonOrder.getOrderNum(),distance);
							//距离小于2km时，将订单派给该订单
							log.info("订单{}距离司机{}米",sonOrder.getOrderNum(),distance);
							Driver driver = driverService.selectByPrimaryKey(order.getDriverId());

							Order result=new Order();
							result.setId(sonOrder.getId());
							result.setDriverId(order.getDriverId());
							result.setOrderStatus(3);
							result.setReceiveTime(new Date());
							result.setParentOrder(order.getOrderNum());
							boolean success=false;
							leftSeat=leftSeat-seat2;
							if(leftSeat<0){
								log.info("所需的座位数大于剩余座位数，逻辑错误");
								continue;
							}
							int pk=orderService.updateByPrimaryKeySelective(result);
							if(pk==1){
								success=orderService.send(sonOrder, driver);
							}
							if(success){
								log.info("拼单成功");
								//当主单不为到达上车点时进行排序
								if(order.getOrderStatus()!=4){
									int EXPIRE = 7200;
									Redis.c.setex(Redis.K.ORDER_CARPOOL.to(order.getOrderNum()), EXPIRE, String.valueOf(leftSeat));
									
									List<Order> list = orderService.selectOrderByParentOrder(order.getOrderNum());
									OrderUtil.sortOrder(list);
								}
								
								return;
							}else{
								log.info("拼单失败");
								continue;
							}
						}else{
							log.info("订单{}与司机{},距离"+distanced,sonOrder.getOrderNum(),order.getDriverId());
							log.info("订单{}与主订单{}终点,距离"+distance,sonOrder.getOrderNum(),order.getOrderNum());
							log.info("订单相隔太远，不匹配");
							continue;
						}
					}
				}
			}
			@Override
			public void onCancelled(SyncError arg0) {
			}
		});
	}
	/**
	 * 定时任务检查优惠卷是否过期
	 */
	public void checkCouponValid()throws Exception{
		log.info("===========检查优惠卷是否过期开始===========");
		List<CouponActivities> calist=activityService.queryCouponActivities();
		List<Coupon> couponlist=activityService.selectNotUsedCoupon();
		for(CouponActivities couponActivities:calist){
			Date endTime=couponActivities.getEndTime();
			long endT=endTime.getTime();
			long nowT=new Date().getTime();
			if(endT<=nowT){//活动结束日期与当前时间对比
				couponActivities.setStatus(CouponActivities.STATUS_OVER);
				activityService.updateByPrimaryKeySelective(couponActivities);
			}
			couponActivities.getId();
			for(Coupon coupon:couponlist){
				if(coupon.getCouponId().equals(couponActivities.getId())){
					endT=endTime.getTime();
					nowT=new Date().getTime();
					if(endT<=nowT){//活动结束日期与当前时间对比
						coupon.setStatus(Coupon.OVER_USED);//已过期
						
						activityService.updateByPrimaryKeySelective(coupon);
						
					}
				}
			}
			
		}
		log.info("===========检查优惠卷是否过期结束===========");
		
	}

	/**
	 * 将预约的拼车单修改订单类型
	 */
	public void changeAppointmentCarpoolToNowCarpool()throws Exception{
		System.out.println("=========预约拼车单=========="+DateUtil.getCurDateTime());
		List<Order> list=orderService.selectAppointmentCarpool();
		log.info("共有{}个15分钟内的预约拼车订单",list.size());
		for(Order order:list){
			order.setOrderType(5);
			order.setCreateTime(DateUtil.beforeNMinsDate(order.getPlanTime(), 5+""));
			order.setStartTime(order.getPlanTime());
			int i=orderService.updateByOrderNumSelective(order);
			if(i==1){
				log.info("订单{}已成功修改",order.getOrderNum());
			}
		}
	}
}